package com.ceba.test.modules.sign.helper;


import com.ceba.base.config.CommonConfig;
import com.ceba.base.entity.CebaSignInfo;
import com.ceba.base.enums.AbcSignTypeEnum;
import com.ceba.base.enums.SealTypeEnum;
import com.ceba.base.helper.SystemCommonHelper;
import com.ceba.base.sign.ClientSign;
import com.ceba.base.utils.PDFUtils;
import com.ceba.base.utils.PdfSignUtils;

import com.ceba.cpdf.ServerPackSignParam;
import com.ceba.cpdf.server.ta.TAPackSignServiceParam;

import com.ceba.cq.bean.params.CQPDFFrontSignParam;
import com.ceba.test.base.config.LogicPathUtil;
import com.ceba.test.base.utils.StringUtil;
import org.json.JSONObject;

import com.ceba.cebacer.CertificateLevelEnum;
import com.ceba.cebacer.EncodeSignType;
import com.ceba.cebacer.HashType;
import com.ceba.cebacer.KeyLoaderType;
import com.ceba.cpdf.bean.PDFParam;
import com.ceba.cpdf.parse.ParamParseUtils;
import com.ceba.cpdf.server.ks.KSPackSignServiceParam;
import com.ceba.cpdf.strategy.CPDFUtils;
import com.ceba.forpdf.pdf.PdfTools;
import com.ceba.forpdf.pdf.entity.PdfPosition;
import com.ceba.service.bean.CMessage;
import com.ceba.service.bean.StatusCodeType;
import com.ceba.test.base.configs.CebaConfig;
import com.ceba.test.base.configs.CebaPathUtil;
import com.ceba.test.base.configs.ServerSignConfig;
import com.ceba.test.base.enums.EditionTypeEnum;
import com.ceba.test.base.helper.SystemHelper;
import com.ceba.test.base.language.ResourceUtils;
import com.ceba.test.modules.admin.entity.GStamp;
import com.ceba.test.modules.admin.entity.ISign;
import com.ceba.test.modules.admin.helper.QRCodeHelper;
import com.ceba.test.modules.statistic.entity.ReportSign;

import abc.util.FileHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class SignInServerHelper {
	static Logger logger = LoggerFactory.getLogger(SignInServerHelper.class);

	static QRCodeHelper qrCodeService = new QRCodeHelper();


	//server情况下微调参数
	public static int stampX_server_w =2;
	public static int stampY_server_h = 2;
	//保证数字签名和直接插入签名位置一致，添加的微调参数
	public static int _param = 4;

	/**
	 * 将章中的部分信息写入接口对象
	 * @param gs
	 * @return
	 */
	public static void copyGSToISign(GStamp gs,ISign iSign,  String pdfPath,int editionType) throws Exception{
		iSign.setImgWidth(gs.getImgWidth());
		iSign.setImgHeight(gs.getImgHeight());
		iSign.setStampPage(gs.getStampPage());

		if(iSign.getKeyType() == SystemHelper.getServerType()){
			gs.setStamp_x(gs.getFloatStamp_x().intValue()+stampX_server_w+"");
			gs.setStamp_y(gs.getFloatStamp_y().intValue()-stampY_server_h+"");
		}
		iSign.setStampX(gs.getStamp_x());
		iSign.setStampY(gs.getStamp_y());
		iSign.setStampFlag(gs.isStampFlag()?"true":"false");
		iSign.setStampPath(LogicPathUtil.getSystemUploadPath(gs.getStorageAddressId())+gs.getFilePath());
		iSign.setMatchName(gs.getMatchName());
		iSign.setRectPageNo(gs.getIntStampPage());
		getPdfPosition(iSign,pdfPath,editionType);
	}

	//需要将章在pdf中的位置进行计算
	private static void getPdfPosition(ISign iSign,String pdfPath,int editonType) throws  Exception{
		if(iSign.getKeyType() == SystemHelper.getServerType() &&
				Integer.valueOf(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType())==iSign.getSignType()){
			PdfPosition po = PdfTools.getPdfPosition(Integer.valueOf(iSign.getStampPage()),
					new Float(iSign.getImgWidth()),new Float(iSign.getImgHeight()),
					Float.valueOf(iSign.getStampX()).intValue(),
					Float.valueOf(iSign.getStampY()).intValue(),pdfPath,PdfPosition.TRANSPRENT_P);
			iSign.setRectTop(new Float(po.getPosition().getLly()).intValue());
			iSign.setRectRight(new Float(po.getPosition().getLlx()).intValue());
			iSign.setRectLeft(new Float(po.getPosition().getUrx()).intValue());
			iSign.setRectBottom(new Float(po.getPosition().getUry()).intValue());
			iSign.setRectPageNo(po.getPosition().getPageNum());
		}
		String stampPage = iSign.getStampPage();
		//如果是API版，且为拖拽签名且后台设置签名页超过文档本身页数
		if(editonType== EditionTypeEnum.API.getType() && Integer.valueOf(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType())==iSign.getSignType()
				&& !PDFUtils.checkPdfPagesEnough(pdfPath, stampPage)){
			iSign.setRectTop(0);
			iSign.setRectRight(0);
			iSign.setRectLeft(0);
			iSign.setRectBottom(0);
		}
	}
	/*
	 * 将I_sign参数赋给PDFParam
	 */
	public static void packISignToPDFParam(PDFParam param,ISign  iSign,String filePath,int editionType) throws Exception{
		iSign.setImgWidth(iSign.getFloatImgWidth().intValue()+"");
		iSign.setImgHeight(iSign.getFloatImgHeight().intValue()+"");
		iSign.setStampX(iSign.getFloatStampX().intValue()+"");
		iSign.setStampY(iSign.getFloatStampY().intValue()+"");
		iSign.setStampPage(iSign.getIntStampPage().intValue()+"");
		getPdfPosition(iSign,filePath,editionType);
		if(iSign.getKeyType()== KeyLoaderType.TYPE_P12) {
			ClientSign sign = new ClientSign();
			sign.setCertificationLevel(SystemHelper.getCertificateLevel());
			JSONObject o = new JSONObject(iSign);
			ClientSign.packStampInfoToClienSign(o, sign);
			ClientSign.packISignToPDFParamP12(param, sign, filePath);
		}else{
			//只要是签名等级1以上的签名，以全局为主
			if(iSign.getCertificationLevel()>=CertificateLevelEnum.YZ.getType()){
				iSign.setCertificationLevel(SystemHelper.getCertificateLevel());
			}
		}
		if(SystemHelper.getServerType() == iSign.getKeyType()){
			param.setKeyType(SystemHelper.getServerType());
		}else{
			param.setKeyType(iSign.getKeyType());
		}
		//位置定位
		if(Integer.valueOf(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType())==iSign.getSignType()){
			iSign.setMatchName("");
		}
		JSONObject object = new JSONObject(iSign);
		object.put("tssType", ServerSignConfig.tsaType);
		object.put("tssUrl", ServerSignConfig.tsaUrl);
		object.put("tssUser", ServerSignConfig.tsaUser);
		object.put("tssPsw", ServerSignConfig.tsaPsw);
		object.put("allowCopy",iSign.getAllowPdfContentCopy() == 0 ? true:false);
		object.put("allowPrinting",iSign.getAllowPdfPrint() == 0 ? true:false);
		object.put("allowAnnotations",SystemHelper.allowPdfAnnotations());
		String encropytToPdf = CebaConfig.ENCROPYT_TO_PDF;
		boolean isEncropytToPdf = true;
		if(!com.ceba.test.base.utils.StringUtil.isEmptyString(encropytToPdf)){
			if(encropytToPdf.equals("false")){
				isEncropytToPdf = false;
			}
		}
		object.put("encropytToPdf",isEncropytToPdf);
        param = ParamParseUtils.parseISignJsonToPDFParam(object.toString(), param);
		//关键字
		if(Integer.valueOf(SealTypeEnum.KEYWORD_STAMP_FLAG.getType())==iSign.getSignType()){
			param.setNeedRect(false);
		}else if(Integer.valueOf(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType())==iSign.getSignType()){
			param.setNeedRect(true);
		}
		param.setNeedLtv(SystemHelper.needLtv());
		param.setNeedCrl(CommonConfig.NEED_CRL);
		param.setNeedOcsp(CommonConfig.NEED_OCSP);
		//签名等级
		if(iSign.getKeyType() == KeyLoaderType.TYPE_CEBA_KEY){
			param.getcSignParam().setCertificationLevel(SystemHelper.getCertificateLevel());
			param.getcSignParam().getDefaultSignInfo().setCertificationLevel(SystemHelper.getCertificateLevel());
			CQPDFFrontSignParam cqPdfFrontSignParam = new CQPDFFrontSignParam();
			if (!StringUtil.isEmptyString(iSign.getPrivateKeyName())) {
				cqPdfFrontSignParam.setPrivateKeyName(iSign.getPrivateKeyName());
				logger.info("packISignToPDFParam: privateKeyName=" + cqPdfFrontSignParam.getPrivateKeyName());
			} else {
				cqPdfFrontSignParam.setPrivateKeyName(iSign.getKeyName());
				logger.info("packISignToPDFParam: keyName=" + cqPdfFrontSignParam.getPrivateKeyName());
			}

			cqPdfFrontSignParam.setTsaType(object.has("tssType") ? object.getInt("tssType") : 0);
			cqPdfFrontSignParam.setTsaUrl(object.has("tssUrl") ? object.getString("tssUrl") : "");
			cqPdfFrontSignParam.setTsaUser(object.has("tssUser") ? object.getString("tssUser") : "");
			cqPdfFrontSignParam.setTsaPsw(object.has("tssPsw") ? object.getString("tssPsw") : "");

			param.setCqSignParm(cqPdfFrontSignParam);
		}else {
			param.getCqSignParm().getSignInfo().setCertificationLevel(iSign.getCertificationLevel());
			param.getCqSignParm().getDefaultSignInfo().setCertificationLevel(iSign.getCertificationLevel());
			param.getCqSignParm().setPrivateKeyName(iSign.getKeyName());
			//软证书已经有判断不需要重复判断
			if (iSign.getKeyType() != KeyLoaderType.TYPE_P12) {
				if (PDFUtils.checkFileHasRSASigned(filePath)) {
					param.getCqSignParm().setPdfHasRSASigned(true);
				}
				if (PDFUtils.checkFileHasSM2Signed(filePath)) {
					param.getCqSignParm().setPdfHasSM2Signed(true);
				}
			}
		}
		//服务器模式才走
		if(SystemHelper.getServerType() == iSign.getKeyType()){
			//如果是rsa签名，则根据配置取hash算法
			if(param.getEncodeSignType() == EncodeSignType.RSA.getCode()){
				param.setHashType(Integer.valueOf(ServerSignConfig.rsaHashType));
			}else{
				param.setHashType(HashType.SM3.getType());
			}
			JSONObject requestObject = new JSONObject();
			requestObject.put("appCode", ServerSignConfig.appCode);
			requestObject.put("appPWD", ServerSignConfig.appPWD);
			if(StringUtil.isEmptyString(iSign.getKeyName())){
				requestObject.put("keyName", iSign.getPrivateKeyName());
			}else{
				requestObject.put("keyName", iSign.getKeyName());
			}
            ServerPackSignParam.packSignParam(param,requestObject,iSign.getKeyType());
		}

	}


	/*
	 * 签名文档
	 */
	public static CMessage signPdf(String filePath,String savePath,ISign[] iSigns,ReportSign  parm) throws Exception{
		CMessage cm = new CMessage();
		if(iSigns.length == 1){
			ISign iSign = iSigns[0];
			PDFParam pdfParam = new PDFParam();

			if(iSign.getKeyType() == KeyLoaderType.TYPE_CEBA_KEY){
				PdfTools.checkSignType(SystemHelper.getAbcSignKeyType(), 0);
				if(AbcSignTypeEnum.File.getCode().equals(SystemHelper.getAbcSignKeyType() )){
					iSign.setKeyType(KeyLoaderType.TYPE_P12);
				}
				packISignToPDFParam(pdfParam, iSign,filePath,parm.getEditionType());
				if(Integer.valueOf(SealTypeEnum.KEYWORD_STAMP_FLAG.getType())==iSign.getSignType()){
					cm =   CPDFUtils.pdfSignByKeyWord(pdfParam, filePath, savePath);
				}else if(Integer.valueOf(SealTypeEnum.DRAFTING_POSTION_STAMP_FLAG.getType())==iSign.getSignType()){
					cm =   CPDFUtils.pdfSignByRectangle(pdfParam, filePath, savePath);
				}
			}else{
				packISignToPDFParam(pdfParam, iSign,filePath,parm.getEditionType());
				if(iSign.getSignType() == 0){
					cm =   CPDFUtils.pdfSignByKeyWord(pdfParam, filePath, savePath);
				}else if(iSign.getSignType() == 1){
					cm =   CPDFUtils.pdfSignByRectangle(pdfParam, filePath, savePath);
				}
			}
		}else{
			PDFParam[]params = new PDFParam[iSigns.length];
			for(int i = 0 ; i < iSigns.length ; i ++){
				ISign iSign = iSigns[i];
				if(iSign.getKeyType() == KeyLoaderType.TYPE_CEBA_KEY){
					cm.setStatusCode(StatusCodeType.CODE_2000.getCode());
					cm.setMessage(StatusCodeType.getMessageByCode(StatusCodeType.CODE_2000.getCode()));
					return cm;
				}
				PDFParam param = new PDFParam();
				packISignToPDFParam(param,iSign,filePath,parm.getEditionType());
				//多签名则均设置为修订签名
				if(iSigns.length >1){
					param.getCqSignParm().getSignInfo().setCertificationLevel(CertificateLevelEnum.XD.getType());
					param.getCqSignParm().getDefaultSignInfo().setCertificationLevel(CertificateLevelEnum.XD.getType());
				}
				params[i] = param;
			}
			cm = CPDFUtils.pdfMultiSign(params, SystemHelper.getServerType(), filePath, savePath);
		}
		
		if(StatusCodeType.CODE_200.getCode().equals(cm.getStatusCode())){
			afterSign(1,savePath, parm);
			cm.setStatusCode(StatusCodeType.CODE_0.getCode());
		}
		
		return cm;
	}

		/**
	 * 签名成功后，更新数据库
	 * @throws Exception
	 */
	public static  void afterSign(int num,String savePath,ReportSign  parm) throws Exception{
		if(num >0){
			//获取文件名
			String name = FileHelper.getFileName(savePath, false)+".pdf";
			parm.setNum(num);
			parm.setFileName(name);
			if(!parm.isTestSign()){
				SignHelper.afterSignReport(savePath,parm);
			}
			
		}
	}
	
	
	/**
	 * 判断文档有无签名
	 * @return
	 * @throws Exception
	 */
	public static JSONObject checkFileHasSigned(String filePath,ISign[] iSigns) throws Exception{
		String ext = FileHelper.getFileExtName(filePath).toLowerCase();
		String fileName = FileHelper.getFileName(filePath);
		int code = 0;
		JSONObject result = new JSONObject();
		StringBuffer sb = new StringBuffer();
		result.put("code", code);
		if(iSigns.length  == 1 && iSigns[0].getKeyType() == KeyLoaderType.TYPE_CEBA_KEY){
			if(PdfSignUtils.checkFileHasSign(filePath) && "pdf".equals(ext)){
				sb.append(ResourceUtils.getMessage("MODULES_PLEASE_FILE")+fileName+ResourceUtils.getMessage("MODULES_HAVE_SIGNED_NAME"));
				result.put("message",sb.toString());
				result.put("code",12);
				return result;
			}
		}else{
			if(CPDFUtils.checkFileHasSM2Signed(filePath)){
				for(ISign iss:iSigns){
					iss.setPdfHasSM2Signed(true);
					iss.setStampFlag("true");
				}
				result.put("code", 1);
			}
			if(CPDFUtils.checkFileHasRSASigned(filePath)){
				for(ISign iss:iSigns){
					iss.setPdfHasRSASigned(true);
					iss.setStampFlag("true");
				}
				result.put("code", 1);
			}
		}
		return result;
	}
}
